Support readonly for all fields - #1677
Merged
Merged
Conversation
Flo0807
reviewed
Dec 5, 2025
The `:readonly` field option, being shared among all fields, has been moved to the `@config_schema` of `Backpex.Field`.
gmazzamuto
force-pushed
the
feature/readonly-fields
branch
from
December 23, 2025 17:27
30ef1e3 to
c2ab647
Compare
Previously the readonly dropdown kept role="button", tabindex=0, and aria-haspopup="true" while stripping the menu, producing a focusable element that announces a popup that isn't there. Also removed the fragile class-token-surgery that reached into caller class lists to delete "input" and "bg-transparent" strings; callers now build their own readonly-aware class lists using Phoenix's list syntax.
The drop target's phx-drop-target attribute was not gated on readonly, so drag-and-drop still started uploads. Cancel buttons for in-progress and existing entries remained clickable, letting users mutate file state. The "Upload a file" <a> rendered as a dead link in readonly mode — now a plain <span> with the interactive classes removed.
text-base-content/40 on bg-base-200 falls below 4.5:1 on stock daisyUI themes. Bumped to /60 to match the codebase's standard muted-text token (used in help_text / labels).
HTML's readonly and disabled have different a11y semantics: disabled
removes the element from the tab order and is frequently skipped by
screen readers in form-review mode, making the readonly value
invisible. For inputs that natively support readonly (text, number,
date, date_time, time, textarea, email, url, currency), keeping only
readonly={@readonly} is correct. Controls without native readonly
(select, multi_select, boolean, relations, upload) continue to use
disabled as before.
Previously the readonly branch removed the delete checkbox but left an orphaned <label for> pointing at nothing, wrapping a <div class="btn btn-disabled"> with sr-only "Delete" text. Screen readers announced a non-interactive "Delete" with a dangling label association. Same problem for "Add entry" — rendered as a disabled checkbox-masquerading-as-button. In readonly mode a user has no use for either control, so they are now omitted entirely.
select_relational_field/1 and pivot_field/1 previously did not receive the parent field's readonly flag. The main UI already hid the triggers that invoke them, so no live regression — but any future path that opens the relation modal (e.g. programmatic push_event, pre-populated newest_relational) would render an editable select on a readonly field. Now both components declare readonly as an explicit attr and forward it to their inputs.
The guide listed only Date, DateTime, Number, Text, Textarea as readonly-capable. With this PR, readonly is a global Backpex.Field option and most field types support it. Documented the three rendering strategies (native-readonly, disabled, custom) and the per-field quirks for Upload, InlineCRUD, HasManyThrough, Boolean.
…ledocs These three fields render readonly with custom UI changes that hide or disable elements beyond the standard readonly/disabled attribute. Added short Readonly sections to the moduledocs so users discover this behavior without reading the guide.
Covers the readonly-branch HTML surface of both components: dropdown has no role/tabindex/aria-haspopup/menu when readonly; multi_select prompt uses /60 contrast and badges render without primary color or remove controls. Sets up test/html/ as the home for future HTML component tests (the repo previously had no component-level coverage).
This fixes a bug caused by Ecto's `:sort_param` and `:drop_param` when the field is readonly. The hidden fields need to be marked as disabled to prevent being sent when the InlineCRUD field is readonly. Otherwise the following bug happens. Steps to reproduce: * in UserLive, set the social_links field as readonly * in the edit view, make any change to the form * the social_links will disappear because Ecto's `cast_embed` doesn't work properly
Contributor
Author
|
Hi there, I have merged the latest develop branch and added an extra commit to fix a bug. What is left to do is to homogenize the look and feel of disabled fields. At the moment, disabled text fields look differently than other fields such as Select. I see that you are favoring the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support
:readonlyoption for all fields.The
:readonlyfield option, being shared among all fields, has been moved to the@config_schemaofBackpex.Field. This should not be a breaking change.Example of readonly fields: